package com.hmkj.web.controller.quote;

import com.hmkj.common.baseMapper.GenericPo;
import com.hmkj.common.entity.ResultEntity;
import com.hmkj.core.constant.CacheID;
import com.hmkj.core.constant.RiskNID;
import com.hmkj.core.model.quote.KlineData;
import com.hmkj.core.model.quote.RealTimeData;
import com.hmkj.core.model.quote.SimpleRealData;
import com.hmkj.core.model.quote.TrendData;
import com.hmkj.core.po.commo.Commo;
import com.hmkj.core.po.operate.Agent;
import com.hmkj.core.po.risk.RiskParam;
import com.hmkj.core.po.user.User;
import com.hmkj.core.service.cache.RedisService;
import com.hmkj.core.service.operate.AgentService;
import com.hmkj.core.service.risk.RiskParamService;
import com.hmkj.web.controller.GenericController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 行情请求相关控制器
 *
 * @author Vector
 * @create 2017-11-13 11:57
 */
@Api(description = "行情请求相关")
@Slf4j
@RestController
@RequestMapping(GenericController.BASE_API_URL + "/quote")
public class QuotationController extends GenericController<Integer, User> {
    @Resource
    private RedisService redisService;
    @Resource
    private RiskParamService riskParamService;
    @Resource
    private AgentService agentService;


    @ApiOperation(value = "获取分时数据", notes = "获取分时数据")
    @RequestMapping(value = "getTrendData", method = RequestMethod.POST)
    public ResultEntity<List<TrendData>> getTrendData(@ApiParam("品种ID") @RequestParam Integer commoId,
                                                      @ApiParam("数据条数") @RequestParam String number) throws Exception {
        log.info("获取分时数据");
        return ok(redisService.getList(CacheID.QUOTE_SLINE_PREFIX + commoId, TrendData.class));
    }


    @ApiOperation(value = "获取K线数据", notes = "获取K线数据")
    @RequestMapping(value = "getKlineData", method = RequestMethod.POST)
    public ResultEntity<List<KlineData>> getKlineData(@ApiParam("品种ID") @RequestParam Integer commoId,
                                                      @ApiParam("K线类型：M1:1分钟K线 M3:3分钟K线 M5:5分钟K线 M15:15分钟K线 M30:30分钟K线 M60:60分钟K线 D1:日K") @RequestParam String type,
                                                      @ApiParam("数据条数，查询日K是必填") @RequestParam(required = false) String number) throws Exception {
        log.info("获取K线数据");
        Commo commo = redisService.get(CacheID.COMMO_ID_PREFIX+commoId,Commo.class);
        if(commo.getType().intValue() == Commo.TYPE.T2.code){
            return ok(redisService.getList(CacheID.QUOTE_KLINE_PREFIX + type + ":" + commoId, KlineData.class));
        }
        if (type.equals(KlineData.TYPE.M1.value)) {
            return ok(buildM1K(redisService.getList(CacheID.QUOTE_SLINE_PREFIX + commoId, TrendData.class)));
        } else {
            return ok(redisService.getList(CacheID.QUOTE_KLINE_PREFIX + type + ":" + commoId, KlineData.class));
        }
    }

    /**
     * 1分钟K线使用分数数据进行转化
     *
     * @param list
     * @return
     */
    private List<KlineData> buildM1K(List<TrendData> list) {
        if (list != null) {
            List<KlineData> klist = new ArrayList<>();
            list.forEach(item -> {
                KlineData data = new KlineData();
                data.setOp(item.getOp());
                data.setCp(item.getCp());
                data.setLp(item.getLp());
                data.setHp(item.getHp());
                data.setDt(item.getDt());
                data.setMt(item.getMt());
                data.setD(item.getD());
                klist.add(data);
            });
            return klist;
        }
        return null;
    }


    @ApiOperation(value = "获取期货风控参数", notes = "获取期货风控参数")
    @RequestMapping(value = "getRiskData", method = RequestMethod.POST)
    public ResultEntity getRiskData(@ApiParam("品种ID") @RequestParam Integer commoId) throws Exception {
        log.info("获取期货风控参数");
        return ok(m -> {
            riskParamService.select(new RiskParam(t -> {
                t.setCommoId(commoId);
                t.setDelFlag(GenericPo.DELFLAG.NORMAL.code);
            })).stream().forEach(riskParam -> {
                m.put(riskParam.getNid(), riskParam.getValue());
            });
            Commo commo = redisService.get(CacheID.COMMO_ID_PREFIX + commoId, Commo.class);
            m.put("name", commo.getName());
            m.put("code", commo.getCode());
            m.put("contract", riskParamService.getContractNo(commoId));
            m.put("is_trade", riskParamService.isTradeTime(commoId));
            if ("HSI".equals(commo.getCode()) || "MHI".equals(commo.getCode())) {
                m.put("currency_type", "CNY");
            } else {
                m.put("currency_type", "USD");
            }
        });
    }


    @ApiOperation(value = "获取期货规则参数", notes = "获取期货规则参数")
    @RequestMapping(value = "getRuleData", method = RequestMethod.POST)
    public ResultEntity getRuleData(@ApiParam("品种ID") @RequestParam Integer commoId) throws Exception {
        log.info("获取期货风控参数");
        // 止损点数
        List<Integer> lspList = riskParamService.getParam2IntList(RiskNID.LOSE_STOP_POINT, commoId);

        // 交易数量
        List<Integer> numList = riskParamService.getParam2IntList(RiskNID.TRADE_NUMBER, commoId);

        // 每点合约价值
        BigDecimal pv = new BigDecimal(riskParamService.getParamValue(RiskNID.POINT_VALUE, commoId));

        // 汇率
        BigDecimal er = new BigDecimal(riskParamService.getParamValue(RiskNID.EXCHANGE_RATE, commoId));

        // 止损比例
        BigDecimal lsr = new BigDecimal(riskParamService.getParamValue(RiskNID.LOSE_STOP_RATE, commoId));

        // 止损比例
        BigDecimal fee;


        // 登录用户
        User user = getLoginUser();
        if (user == null) {
            // 未登录，手续费取当前代理商的手续费
            Agent agent = agentService.selectOne(new Agent(t -> {
                t.setDomain(getDomain());
                t.setStatus(Agent.STATUS.T1.code);
                t.setDelFlag(Agent.DELFLAG.NORMAL.code);
            }));

            fee = riskParamService.getFeeByAgent(commoId, agent.getId());

        } else {
            // 已登录，手续费取用户所属代理商的手续费
            fee = riskParamService.getFeeByAgent(commoId, user.getAgentId());
        }

        List moneyArr = new ArrayList<>();
        for (Integer num : numList) {
            List items = new ArrayList<>();
            for (Integer lsp : lspList) {
                Map<String, String> map = new HashMap<>();
                // 计算止损
                BigDecimal ls = pv.multiply(new BigDecimal(lsp * num)).multiply(er).setScale(2, BigDecimal.ROUND_HALF_UP);
                // 计算保证金
                BigDecimal deposit = ls.divide(lsr, 2, BigDecimal.ROUND_HALF_UP);
                map.put("num", num.toString());
                map.put("a", ls.toString());
                map.put("b", deposit.toString());
                items.add(map);
            }
            moneyArr.add(items);
        }
        BigDecimal finalFee = fee;
        return ok(m -> {
            m.put("moneyArr",moneyArr);
            m.put("numArr",numList);
            m.put("fee", finalFee);
        });
    }


    @ApiOperation(value = "获取期货实时行情数据", notes = "获取期货实时行情数据")
    @RequestMapping(value = "getRealData", method = RequestMethod.POST)
    public ResultEntity<RealTimeData> getRealData(@ApiParam("品种ID") @RequestParam Integer commoId) throws Exception {
        log.info("获取期货实时行情数据");
        return ok(redisService.get(CacheID.QUOTE_REAL_PREFIX + commoId, RealTimeData.class));
    }


    @ApiOperation(value = "期货单个品种简要行情", notes = "期货单个品种简要行情")
    @RequestMapping(value = "simpleQuotation", method = RequestMethod.POST)
    public ResultEntity simpleQuotation(@ApiParam("品种ID") @RequestParam Integer commoId) throws Exception {
        log.info("期货单个品种简要行情");
        return ok(redisService.mapGet(CacheID.QUOTE_SIMPLEREAL_MAP, commoId.toString(), SimpleRealData.class));
    }

    @ApiOperation(value = "期货所有品种简要行情", notes = "期货所有品种简要行情")
    @RequestMapping(value = "allSimpleQuotation", method = RequestMethod.POST)
    public ResultEntity allSimpleQuotation() throws Exception {
        log.info("期货所有品种简要行情");
        return ok(redisService.map(CacheID.QUOTE_SIMPLEREAL_MAP));
    }
}
